﻿using System;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Btstack;

namespace TestClient
{
    class Program
    {
        static void Main(string[] args)
        {
            var bt = new Bluetooth();

            Console.CancelKeyPress += delegate {
                Console.WriteLine("CTRL-C - SIGINT received, shutting down..");

                bt.PowerOff();

                Console.WriteLine("Exit.");

                Environment.Exit(1);
            };

            bt.OnWorking += () =>
            {
                Console.WriteLine("BTstack up and running at {0}", BitConverter.ToString(bt.LocalBdAddr).Replace("-", ":"));

                bt.StartScan(Bluetooth.ScanType.Active);
            };

            bt.OnAdvertisingReport += (type, addr, AddrType, name, Rssi) =>
            {
                var AddrStr = BitConverter.ToString(addr).Replace("-", ":");

                Console.WriteLine($"Type: {type,-20}    Addr type: {AddrType,-23}    Addr: {AddrStr}   RSSI: {Rssi:D2} db   Name: {name}");

                if (name == "btstack")
                {
                    bt.StopScan();
                    bt.Connect(addr, AddrType);
                }
            };

            bt.OnConnected += (status, handle, role, interval, latency) =>
            {
                Console.WriteLine($"Connected: 0x{status:x2} 0x{handle:x4} {role} {interval:F2} {latency}");
            };

            bt.OnDiscoverServiceComplete += async () =>
            {
                Console.WriteLine("OnDiscoverServiceComplete");

                foreach (var si in bt.Services)
                {
                    var s = si.service;

                    Console.Write("* service: [0x{0:x4}-0x{1:x4}], uuid ", s.StartGroupHandle, s.EndGroupHandle);
                    if (s.uuid16 > 0)
                        Console.WriteLine("{0:x4}", s.uuid16);
                    else
                        Console.WriteLine(Bluetooth.Uuid128ToStr(s.uuid128));

                    foreach (var c in si.characteristics)
                    {
                        Console.Write("    * characteristic: [0x{0:x4}-0x{1:x4}-0x{2:x4}], properties 0x{3:x2}, uuid ",
                            c.StartHandle, c.ValueHandle, c.EndHandle, c.properties);
                        if (c.uuid16 > 0)
                            Console.WriteLine($"{c.uuid16:x4}");
                        else
                            Console.WriteLine(Bluetooth.Uuid128ToStr(c.uuid128));
                    }
                }

                bt.WriteValueOfCharacteristicWithoutResponse(0x1001, System.Text.Encoding.UTF8.GetBytes("I'm BTStack.net!"));

                Console.WriteLine("Listen all characteristics...");
                bt.ListenForCharacteristicValueUpdates((pt, ch, PacketPtr, size) =>
                {
                    byte[] packet = new byte[size];
                    Marshal.Copy(PacketPtr, packet, 0, size);

                    var ValueHandle = Bluetooth.GattEventNotificationGetValueHandle(packet);
                    var value = Bluetooth.GattEventNotificationGetValue(packet);

                    Console.WriteLine("0x{0:x4}: Updates: 0x{1}", ValueHandle, BitConverter.ToString(value).Replace("-", ""));
                }, -1);

                bt.WriteClientCharacteristicConfiguration(0x1001, Bluetooth.GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION);
                await Task.Delay(1000);
                bt.WriteClientCharacteristicConfiguration(0x1002, Bluetooth.GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION);
            };

            bt.OnDisconnected += (handle, status, reason) =>
            {
                Console.WriteLine($"Disconnected: 0x{handle:x4} 0x{status:x2} 0x{reason:x2}");

                switch (reason)
                {
                    case Bluetooth.ERROR_CODE_REMOTE_USER_TERMINATED_CONNECTION:
                        Console.WriteLine("Terminated by remote");
                        break;

                    case Bluetooth.ERROR_CODE_CONNECTION_TERMINATED_BY_LOCAL_HOST:
                        Console.WriteLine("Terminated by local");
                        break;

                    case Bluetooth.ERROR_CODE_CONNECTION_TIMEOUT:
                        Console.WriteLine("Connect timeout");
                        break;

                    default:
                        break;
                }

                bt.StartScan(Bluetooth.ScanType.Active);
            };

            bt.OnPowerOnFailed += () =>
            {
                Console.WriteLine("Power on failed");
            };

            bt.PowerOn();

            bt.StartRunLoop();
        }
    }
}
